#include "Spark/Net/EventLoop.h"
#include "Spark/Net/EventLoopThread.h"
#include "Spark/Utils/Date.h"
#include <thread>
#include <stdio.h>
#include <unistd.h>

int cnt = 0;
EventLoop *g_loop;

void printTid()
{
    auto id = std::this_thread::get_id();
    auto tid = reinterpret_cast<pthread_t &>(id);
    printf("pid = %d, tid = %lu\n", getpid(), tid);
    printf("now %s\n", TimePoint::Now().toString().c_str());
}

void print(const char *msg)
{
    printf("msg %s %s\n", TimePoint::Now().toString().c_str(), msg);
    if (++cnt == 20)
    {
        g_loop->quit();
    }
}

void cancel(TimerID timer)
{
    g_loop->disableTimer(timer);
    printf("cancelled id[%zu] at %s\n",
           timer,
           TimePoint::Now().toString().c_str());
}

int main()
{
    printTid();
    sleep(1);
    {
        EventLoop loop;
        g_loop = &loop;

        print("main");
        loop.runAfter(1_s, std::bind(print, "once1"));
        loop.runAfter(1.5_s, std::bind(print, "once1.5"));
        loop.runAfter(2.5_s, std::bind(print, "once2.5"));
        loop.runAfter(3.5_s, std::bind(print, "once3.5"));
        TimerID t45 = loop.runAfter(4500_ms, std::bind(print, "once4.5"));
        loop.runAfter(4.2_s, std::bind(cancel, t45));
        loop.runAfter(4.8_s, std::bind(cancel, t45));
        loop.runEvery(2_s, std::bind(print, "every2"));
        TimerID t3 = loop.runEvery(3_s, std::bind(print, "every3"));
        loop.runAfter(9.001_s, std::bind(cancel, t3));

        loop.loop();
        print("main loop exits");
    }
    sleep(1);
    {
        EventLoopThread loopThread;
        EventLoop *loop = loopThread.run();
        loop->runAfter(2_s, printTid);
        sleep(3);
        print("thread loop exits");
    }
}